/**
 * Copyright (c) 2016-2020 https://github.com/zhaohuatai
 *
 * contact z_huatai@qq.com
 *  
 */

package org.zfes.snowier.cloud.zbss.tts.util;

import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Currency;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.NumberUtils;
import org.springframework.util.StringUtils;
import com.google.common.collect.Lists;



public class ZStrUtil extends org.apache.commons.lang3.StringUtils{

	public static List<Long> splitLong(String value) {
		return splitLong( value,",");
	}
	
	public static List<Long> splitLong(String value,String split) {
		if(hasNoText(value)){
			return Lists.newArrayList();
		}
		List<Long> idList=Stream.of(value.split(split)).map(val->Long.valueOf(val)).collect(Collectors.toList());
		return idList;
	}
	
	public static boolean hasText(String str)    {
		return StringUtils.hasText(str);
	}
	public static boolean hasNoText(String str)    {
		return !StringUtils.hasText(str);
	}
	public static boolean hasLength(String str)    {
		return StringUtils.hasLength(str);
	}
	public List<String> arrayToList(String[] args){
		List<String> list=Lists.newArrayList();
		if(args==null||args.length==0){
			return list;
		}
		return Stream.of(args).filter(str->ZStrUtil.hasText(str)).collect(Collectors.toList());
	}
	
	public List<String> arrayToListNoDup(String[] args){
		List<String> list=Lists.newArrayList();
		if(args==null||args.length==0){
			return list;
		}
		return Stream.of(args).filter(str->(ZStrUtil.hasText(str)&&!list.contains(str))).collect(Collectors.toList());
	}
	
	public static String replaceAllWhitespace(String str,String tobeChar) {
		if (!hasLength(str)) {
			return str;
		}

		int len = str.length();
		StringBuilder sb = new StringBuilder(str.length());
		for (int i = 0; i < len; i++) {
			char c = str.charAt(i);
			if(Character.isWhitespace(c)) {
				sb.append(tobeChar);
			}else {
				sb.append(c);
			}
		}
		return sb.toString();
	}
	
	
	public static String UnitAllSpace(String str)    {
		if(str==null){
			return "";
		}
		return str.replaceAll("\\[s]+", "");
    }
	public static Object trimToNull(Object obj){
		if(obj==null){
			return null;
		}
		if(obj instanceof java.lang.String){
			String str=String.valueOf(obj);
			if(str==null||"".equals(str.trim())){
				return null;
			}else{
				return str.trim();
			}
		}
		return obj;
	}
	public static Object trimToEmpty(Object obj){
		if(obj==null){
			return null;
		}
		if(obj instanceof java.lang.String){
			String str=String.valueOf(obj);
			if(str==null||"".equals(str.trim())){
				return "";
			}else{
				return str.trim();
			}
		}
		return obj;
	}
	 @Deprecated
	public static boolean isEmptyAfTrimE(String str){
		return isEmpty(trimToEmpty(str));
	}
	 @Deprecated
	public static boolean isNullAfTrimN(String str){
		return  null==trimToNull(str);
	}
	//------------------------------------------------------------
	public static String parseToSplitStr(List<?> value) {
		if(value==null||value.size()==0){
			return "";
		}
		String str=ZStrUtil.join(value,",");
		return str;
	}
	
	public static String parseToSplitStr(Object[] value) {
		if(value==null||value.length==0){
			return "";
		}
		String str=ZStrUtil.join(value,",");
		return str;
	}
	
	
    public static String toLowerCaseFirst(String s){
        if(Character.isLowerCase(s.charAt(0))) {
        	 return s;
        }else {
        	 return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }
    public static String toUpCaseFirst(String s){
        if(Character.isUpperCase(s.charAt(0))) {
            return s;
        }else{
        	 return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
        }

    }
        
	//1,2,3
	public static Long[] parseToLongArray(String value) {
		return Stream.of(value.split(",")).map(str -> Long.parseLong(str)).toArray(Long[]::new);
	}
	 public static boolean checkEmail(String email){
		  boolean flag = false;
		    String check = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
		    Pattern regex = Pattern.compile(check);
		    Matcher matcher = regex.matcher(email);
		    flag = matcher.matches();
		  return flag;
		 }
	/**
	 * 判断字符串是否符合   正则表达式
	 * @param input
	 * @param regex
	 * @return
	 */
	public static boolean verifyWord(String input, String regex) {
		if (input == null)
			input = "";
		if (regex == null)
			regex = "";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(input);
		boolean flag = m.matches();
		return flag;
	}
	
	/**
	 * 字符串数组中每个元素首字母大写
	 * @param str
	 * @return
	 */
	public static String[] toUpCaseFirst(String[] str) {
		if (str == null || str.length == 0)
			return str;
		String[] result=Stream.of(str).map(strx->toUpCaseFirst(strx)).toArray(String[]::new);
		return result;
	}
	//------------------------------------------------------------
	public static void main(String[] sd){
        String[] result = toUpCaseFirst(new String[]{"abc", "dsfd"});
		Stream.of(result).forEach(System.out::println);
	}

	/**
	 * 是否是降序或者升序
	 * @param str
	 * @param ascOrDesc
	 * @return
	 */
	public static boolean isAscDesc(String str, int ascOrDesc) {
		char last = (char) (str.charAt(0) - ascOrDesc);
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			if (c != (last + ascOrDesc)) {
				return false;
			}
			last = c;
		}
		return true;
	}

	public static int strCountChar(String str,char c){
		int num = 0;
		char[] chars = str.toCharArray();
		for(int i = 0; i < chars.length; i++){
		    if(c == chars[i]){
		    	num++;
		    }
		}
		return num;
	}


	public static String strArrToStr(String[] str,String jionChar){
		StringBuffer sb=new StringBuffer();
		for (String string : str) {
			sb.append(string).append(jionChar);
		}
		return sb.toString();
	}
	
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Object convert(final Class<?> toClazz,String sourceValue){
		if(toClazz.isAssignableFrom(java.lang.Long.class)  ){
			return Long.valueOf(sourceValue);
		}if(toClazz.isAssignableFrom(java.lang.Integer.class)  ){
			return Integer.valueOf(sourceValue);
		}if(toClazz.isAssignableFrom(java.lang.String.class)  ){
			return sourceValue;
		}if(toClazz.isAssignableFrom(java.lang.Character.class)  ){
			return sourceValue;
		}if(toClazz.isAssignableFrom(java.lang.Short.class)  ){
			return Short.valueOf(sourceValue);
		}if(toClazz.isAssignableFrom(java.lang.Byte.class)  ){
			return Byte.valueOf(sourceValue);
		}if(toClazz.isAssignableFrom(java.lang.Double.class)  ){
			return Double.valueOf(sourceValue);
		}if(toClazz.isAssignableFrom(java.lang.Float.class)  ){
			return Float.valueOf(sourceValue);
		}else if(toClazz.isAssignableFrom(java.lang.Boolean.class)  ){
			if (sourceValue==null) {
				return null;
			}
			String value = sourceValue.trim();
			if ("".equals(value)) {
				return null;
			}
			value = value.toLowerCase();
			if (trueValues.contains(value)) {
				return Boolean.TRUE;
			}else if (falseValues.contains(value)) {
				return Boolean.FALSE;
			}else {
				throw new IllegalArgumentException("Invalid boolean value '" + sourceValue + "'");
			}
		}if(toClazz.isAssignableFrom(java.math.BigDecimal.class)  ){
			if(sourceValue.indexOf(".")>0){
				return BigDecimal.valueOf(Long.valueOf(sourceValue));
			}else{
				return BigDecimal.valueOf(Double.valueOf(sourceValue));
			}
		}if(toClazz.isAssignableFrom(java.lang.Number.class)  ){
			return new StringToNumber(toClazz);
			
		}if(toClazz.isAssignableFrom(java.lang.Enum.class)  ){
			Class<?> enumType = toClazz;
			while (enumType != null && !enumType.isEnum()) {
				enumType = enumType.getSuperclass();
			}
			if (enumType == null) {
				throw new IllegalArgumentException("The target type " + toClazz.getName() + " does not refer to an enum");
			}
			return new StringToEnum(enumType);
			
		}if(toClazz.isAssignableFrom(java.math.BigInteger.class)  ){
			 return Charset.forName(sourceValue);
		}if(toClazz.isAssignableFrom(java.nio.charset.Charset.class)  ){
			return Charset.forName(sourceValue);
		}if(toClazz.isAssignableFrom(java.util.Currency.class)  ){
			return Currency.getInstance(sourceValue);
		}if(toClazz.isAssignableFrom(java.util.Locale.class)  ){
			return StringUtils.parseLocaleString(sourceValue);
		}if(toClazz.isAssignableFrom(java.util.Properties.class)  ){
			try {
				Properties props = new Properties();
				// Must use the ISO-8859-1 encoding because Properties.load(stream) expects it.
				props.load(new ByteArrayInputStream(sourceValue.getBytes(StandardCharsets.ISO_8859_1)));
				return props;
			}
			catch (Exception ex) {
				throw new IllegalArgumentException("Failed to parse [" + sourceValue + "] into Properties", ex);
			}
		}else if(toClazz.isAssignableFrom(java.util.TimeZone.class)  ){
			return StringUtils.parseTimeZoneString(sourceValue);
		}else if(toClazz.isAssignableFrom(java.util.UUID.class)  ){
			return (StringUtils.hasLength(sourceValue) ? UUID.fromString(sourceValue.trim()) : null);
		}
		return null;
	}
	private static final class StringToNumber<T extends Number> implements Converter<String, T> {
		private final Class<T> targetType;
		public StringToNumber(Class<T> targetType) {
			this.targetType = targetType;
		}
		@Override
		public T convert(String source) {
			if (source.length() == 0) {
				return null;
			}
			return NumberUtils.parseNumber(source, this.targetType);
		}
	}
	@SuppressWarnings("rawtypes")
	public static class StringToEnum<T extends Enum> implements Converter<String, T> {
		private final Class<T> enumType;
		public StringToEnum(Class<T> enumType) {
			this.enumType = enumType;
		}
		@SuppressWarnings("unchecked")
		@Override
		public T convert(String source) {
			if (source.length() == 0) {
				// It's an empty enum identifier: reset the enum value to null.
				return null;
			}
			return (T) Enum.valueOf(this.enumType, source.trim());
		}
	}
	private static final Set<String> trueValues = new HashSet<String>(4);

	private static final Set<String> falseValues = new HashSet<String>(4);

	static {
		trueValues.add("true");
		trueValues.add("on");
		trueValues.add("yes");
		
		trueValues.add("TRUE");
		trueValues.add("ON");
		trueValues.add("YES");
		trueValues.add("1");

		falseValues.add("false");
		falseValues.add("off");
		falseValues.add("no");
		falseValues.add("FALSE");
		falseValues.add("OFF");
		falseValues.add("NO");
		falseValues.add("0");
	}
}
